#!/usr/bin/env python

"""
This is a test of the database of contacts.

A merged database must pass the set of tests for non-merged database
plus the following tests.

Implemented tests:
* test_contacts_to_self()
  - searches contacts with same donor as acceptor and fails if it finds any
* test_contacts_to_water()
  - there must be no contacts to water

"""

__version__ = "$Id$"

import unittest
import sqlite3
import sys
import logging

log = logging.getLogger("test_merged_database")
log.addHandler(logging.StreamHandler())

class DatabaseTest(unittest.TestCase):
    def __init__(self, DB):
    	self.conn = sqlite3.connect(DB)
    	self.cur = self.conn.cursor()
    	
    	self.tables = self.cur.execute("""SELECT name FROM sqlite_master
                    WHERE type='table' AND name LIKE 'contacts_%'
                    ORDER BY name""").fetchall()
        
        self.test_contacts_to_self()
        self.test_contacts_to_water()
        
    def test_contacts_to_self(self):
        log.info("test_contacts_to_self:")
        for (table, ) in self.tables:
            log.info("  %s" % table)
            r = self.cur.execute("""SELECT COUNT(*) FROM %s
                             WHERE donor_id = acceptor_id""" % table)
            r = r.fetchall()
            assert len(r) == 1
            self.assertEquals(r[0][0],0, "%d self contacts found in %s" % (r[0][0], table))

    def test_contacts_to_water(self):
        """ there should be no contacts of type HOH-* or *-HOH"""
        log.info("test_contacts_to_water:")
        for (table,) in self.tables:            
            SQL = """SELECT contacts.id, donor.amino, acceptor.amino FROM
                     contacts_%(pdb)s AS contacts
                        JOIN atoms_%(pdb)s AS donor
                           ON donor.id = contacts.donor_id
                        JOIN atoms_%(pdb)s AS acceptor
                           ON acceptor.id = contacts.acceptor_id
                     WHERE donor.amino = "HOH" OR acceptor.amino = "HOH"
                     """
            pdb = table.split('_')[1]
            log.info("  %s" % pdb)
            r = self.cur.execute(SQL % {'pdb' : pdb})
            r = r.fetchall()
            self.failUnless(len(r) == 0, "table %s:\n%s" % (table, r))

if __name__ == "__main__":
    DB = "db.sqlite"
    log.setLevel(logging.WARN)
    
    if len(sys.argv) > 1:
        DB = sys.argv.pop(1)
    
    DatabaseTest(DB)
    print "OK"
